#include "app_task.h"

static TaskHandle_t               key_task_Handle = NULL;
static TaskHandle_t               led_display_task_Handle = NULL;
static QueueHandle_t              output_msg_queue = NULL;
static EventGroupHandle_t         event = NULL;
extern charge_state_t charge_state;
static uint8_t led_tog;
static breast_output_msg_t *output_msg = NULL;


static void app_sys_sleep()
{
    sleep_wakeup_type state = 0;

    sys_sleep((uint8_t*)&state);   
 
    if(state == POWER_KEY_WAKEUP)
    {
        led_display_on_all();
        vTaskDelay(1000);
//        led_display_off_all();
        xEventGroupClearBits(event,BREAST_SLEEP_BIT);
        xEventGroupSetBits(event,BREAST_PUMP_PAUSE_BIT);
    }
    else if(state == CHARGE_WAKEUP)
    {
        xEventGroupClearBits(event, BREAST_SLEEP_BIT);
        xEventGroupSetBits(event,BREAST_BAT_CHARGE_BIT);
        return;
    }
    else if(state == BAT_POWER_LOW_WAKEUP)
    {
        xEventGroupClearBits(event, BREAST_SLEEP_BIT);
        xEventGroupSetBits(event,BREAST_BAT_POWER_LOW_BIT);
        return;
    }
}

static void msg_strcut_init(led_packet_t* msg)
{
    uint8_t  bat_gear = 0;
    uint16_t volt = 0;
    msg->systeam_tick = 0;
    msg->tim_set_timeout = 0;
    volt = get_bat_volt();
//    volt -= 100;
    bat_gear = bat_led_gear(volt);
    if(bat_gear == 0x0f )
    {
        xEventGroupClearBits(event, BREAST_SYS_ALL_BIT);
        xEventGroupSetBits(event,BREAST_BAT_POWER_LOW_BIT);
        low_power_state = pdTRUE;
    }
    else
    {
        if(bat_gear == 1)
        {
           led_display_LEVEL(LOW_POW_DIS_LEVEL);
        }
        msg->bat_st = (bat_st_t)bat_gear;
    }
}

static void app_tim_division(uint8_t tim,uint8_t *tens,uint8_t *units)
{
    *tens= (uint8_t)tim / 10;
    *units= (uint8_t)(tim % 10);
}

static void app_ctrl_mode_set(breast_output_msg_t *sys)
{
    mode_select((void *)sys);
}

static void app_gear_default_set(breast_output_msg_t *sys)
{
	sys->packet.suckle_gear_para = THIRD_GEAR;
	sys->packet.knead_gear_para = THIRD_GEAR;
	sys->packet.mode_gether = KNEAD_MODE;
        sys->packet.task_min_set = 30;
}

static void led_display_bat_flicker(uint8_t bat)
{
    led_display_off_all();
    led_tog ^= 1;
    if(led_tog) 
    {
        led_display_bat(bat);
    } 
    else 
    {
        led_display_bat(bat - 1);
    }
}


static void led_display_bat_powerLow(void)
{
    led_tog ^= 1;
    if(led_tog)
    {
        led_display_bat(0);
    }
    else
    {
        led_display_off_all();
    }
}

static void led_display_pause_state(led_packet_t *led_msg)
{
    uint8_t tens = 0;
    uint8_t units = 0;
    uint8_t gear = 0;
    
    led_display_stop_on();
    led_display_vacuum_on();
    led_dispialy_timIcon_on();
    led_display_bat(led_msg->bat_st);
    app_tim_division(led_msg->task_min_set,&tens,&units);
    led_display_tens_digit(tens); 
    led_display_units_digit(units);
    led_display_symbol(led_msg->mode_gether);
    if(led_msg->mode_gether == SUCKLE_MODE)
    {
        gear = led_msg->suckle_gear_para;
    }
    else
    {
        gear = led_msg->knead_gear_para;
    }
    led_display_shift(gear + 1);   
}

static void led_display_run_tim_set(led_packet_t *led_msg)
{
    uint8_t gear = 0;

    led_display_stop_off();
    led_display_vacuum_on();
    led_dispialy_timIcon_on();
    led_display_tens_digit(led_msg->task_tens); 
    led_display_units_digit(led_msg->task_units);
    led_display_bat(led_msg->bat_st);
    led_display_symbol(led_msg->mode_gether);
    if(led_msg->mode_gether == SUCKLE_MODE)
    {
        gear = led_msg->suckle_gear_para;
    }
    else
    {
        gear = led_msg->knead_gear_para;
    }
    led_display_shift(gear + 1);     
}

static void led_display_tim_set(led_packet_t *led_msg)
{
    uint8_t tens = 0;
    uint8_t units = 0;

    app_tim_division(led_msg->task_min_set,&tens,&units);
    led_display_bat(led_msg->bat_st);
    led_display_stop_on();
    led_display_vacuum_on();
    led_display_units_digit(units);
    led_display_tens_digit(tens);
}


static void led_display_timIcon_tog(void)
{ 
    led_tog ^= 1;
    if(led_tog)
    {
        led_dispialy_timIcon_on();
    }
    else
    {
        led_dispialy_timIcon_off();
    }
    
}

void led_display_task(void* args)
{
    led_packet_t *led_msg = NULL;
    uint8_t tick = 0;

    led_msg =  (led_packet_t *)args;

    while(1)
    {
        if( (xEventGroupGetBits(event) & BREAST_SLEEP_BIT ) != BREAST_SLEEP_BIT )
        {           
            switch(led_msg->task_status)
            {
                case BREAST_PUMP_PAUSE:
                {
                    led_display_pause_state(led_msg);
                    break;
                }

                case BREAST_PUMP_START:
                {
                    led_display_run_tim_set(led_msg);
                    break;
                }

                case BREAST_BAT_CHARGE:
                {
                    if((tick++) >= 5)
                    {
                        tick = 0;
                        led_display_bat_flicker(led_msg->bat_st);
                    }
                    break;
                }

                case BREAST_BAT_POWER_LOW: 
                {
                    if((tick++) >= 5)
                    {
                        tick = 0;
                        led_display_bat_powerLow();
                    }
                    break;
                }

                case BREAST_TIM_SET:
                {
                    led_display_tim_set(led_msg);
                    if(tick == 0) 
                      led_tog = 1;

                    if(((tick++) % 5) == 0)
                    {
                        led_display_timIcon_tog();
                    }    
                    break;
                }  

                case BREAST_SLEEP:
                {

                }
            }
        }
        vTaskDelay(100);
    }
}

void key_task(void* args)
{
    uint8_t key_s = 0;
    uint8_t *pGear = NULL;
    breast_output_msg_t *output_msg = NULL;
    EventBits_t bits  = 0;
    output_msg = (breast_output_msg_t *)args;

    uint8_t last_min_set;
    xEventGroupSetBits(event,BREAST_SLEEP_BIT);
    fun_led_packet(&output_msg->packet);
    while(1)
    {
        bits = xEventGroupGetBits(event);   
        if((( bits & BREAST_PUMP_PAUSE_BIT ) != 0) ||   
            ((bits & BREAST_PUMP_START_BIT ) != 0) || 
            ((bits & BREAST_TIM_SET_BIT ) != 0)||
              ((bits & BREAST_VALVE_AEROFLUXUS_BIT ) != 0))
        {
            if(output_msg->packet.mode_gether == SUCKLE_MODE) 
            {
                pGear = (uint8_t *)&output_msg->packet.suckle_gear_para;
            } 
            else 
            {
                pGear = (uint8_t *)&output_msg->packet.knead_gear_para;
            }
    
            bsp_KeyScan(); 
            key_s = bsp_GetKey(); 
            if (key_s != KEY_NONE)
            {
                switch(key_s)
                {
                //start
                case KEY_START_STOP:
                    {
                        output_msg->packet.tim_set_timeout = 0;
                        if( (bits & BREAST_PUMP_START_BIT ) != BREAST_PUMP_START_BIT )
                        {
                            app_ctrl_mode_set(output_msg);
                            xEventGroupClearBits(event,BREAST_SYS_ALL_BIT);
                            xEventGroupSetBits(event,BREAST_PUMP_START_BIT);
                        }
                        else
                        {
                           
                            xEventGroupClearBits(event,BREAST_PUMP_START_BIT);
                            xEventGroupSetBits(event,BREAST_PUMP_PAUSE_BIT);
                             VALVA_AEROFLUXUS_START();
//                            xEventGroupClearBits(event,BREAST_PUMP_START_BIT);
//                            xEventGroupSetBits(event, BREAST_VALVE_AEROFLUXUS_BIT);
                        }
                        if( (bits & BREAST_TIM_SET_BIT ) == BREAST_TIM_SET_BIT )
                        {
                            output_msg->packet.systeam_tick = 0;
                            xEventGroupClearBits(event,BREAST_TIM_SET_BIT | BREAST_PUMP_START_BIT);
                            xEventGroupSetBits(event,BREAST_PUMP_PAUSE_BIT);
                           
                        }
                        xQueueSend(output_msg_queue,output_msg,0);
                        break;
                    }   
                //
                case KEY_MODE_HANDOVER:
                    {
                        output_msg->packet.tim_set_timeout = 0;
                        if( (bits & BREAST_TIM_SET_BIT ) == BREAST_TIM_SET_BIT )
                        {
                            output_msg->packet.task_min_set = last_min_set;
                            xEventGroupClearBits(event,BREAST_TIM_SET_BIT | BREAST_PUMP_START_BIT);
                            xEventGroupSetBits(event,BREAST_PUMP_PAUSE_BIT);
                        }
                        else
                        {
                            output_msg->packet.mode_gether += 1;
                            if(output_msg->packet.mode_gether > SUCKLE_MODE) 
                            {
                                output_msg->packet.mode_gether = KNEAD_MODE;
                            }	
                            app_ctrl_mode_set(output_msg); 
                        }
                        xQueueSend(output_msg_queue,output_msg,0);
                        break; 
                    }
                //
                case KEY_MODE_LONG_DEFAULT:     
                    {   
                        output_msg->packet.tim_set_timeout = 0; 
                        xEventGroupClearBits(event,BREAST_SYS_ALL_BIT);
                        xEventGroupSetBits(event,BREAST_SLEEP_BIT);
                        app_gear_default_set(output_msg);  
                        VALVA_AEROFLUXUS_START();
                        xQueueSend(output_msg_queue,output_msg,0);
                        break;
                    }
                //
                case KEY_GEAR_ADD:
                case KEY_GEAR_AUTO_ADD:
                    {
                         output_msg->packet.tim_set_timeout = 0;
                        if( (bits & BREAST_TIM_SET_BIT ) == BREAST_TIM_SET_BIT )
                        {
                            output_msg->packet.task_min_set += 1;
                            if(output_msg->packet.task_min_set >= 30) 
                            {
                                output_msg->packet.task_min_set = 30;
                            }
 //                           output_msg->packet.tim_set_timeout = 0;
                        }
                        else
                        {
                            *pGear += 1;
                            if(*pGear >= NINTH_GEAR) 
                            {
                                *pGear = NINTH_GEAR;
                            }  
                          
                          
                        }
                          xQueueSend(output_msg_queue,output_msg,0); 
                        break;
                    }
                //
                case KEY_GEAR_SUBTRACT:
                case KEY_GEAR_AUTO_SUBTRACT:
                    {
                      output_msg->packet.tim_set_timeout = 0;
                        if( (bits & BREAST_TIM_SET_BIT ) == BREAST_TIM_SET_BIT )
                        {
                            output_msg->packet.task_min_set -= 1;
                            if((output_msg->packet.task_min_set <= 5)|| (output_msg->packet.task_min_set >= 30))
                            {
                                output_msg->packet.task_min_set = 5;
                            }
 //                           output_msg->packet.tim_set_timeout = 0;
                        }
                        else
                        {
                            *pGear -= 1;
                            if((*pGear<=FIRST_GEAR) || (*pGear >= NINTH_GEAR))
                            {
                                *pGear = FIRST_GEAR;
                            }
                           
                            
                        }
                         xQueueSend(output_msg_queue,output_msg,0); 
                        break;
                    }
                //
                case KEY_POWER:
                    {
                        xEventGroupClearBits(event,BREAST_SYS_ALL_BIT);
                        xEventGroupSetBits(event,BREAST_SLEEP_BIT);   
                        if((bits & BREAST_PUMP_START_BIT ) == BREAST_PUMP_START_BIT )
                        {
                            VALVA_AEROFLUXUS_START();
                        }
                                                               
                        break;
                    }
                //
                case KEY_TIM_SET:
                    { 
                        output_msg->packet.tim_set_timeout = 0;
                        //
                        if( (bits & BREAST_TIM_SET_BIT ) != BREAST_TIM_SET_BIT )
                        {
                            xEventGroupClearBits(event,BREAST_PUMP_START_BIT | BREAST_PUMP_PAUSE_BIT);
                            xEventGroupSetBits(event,BREAST_TIM_SET_BIT);
                            if( (bits & BREAST_PUMP_START_BIT ) == BREAST_PUMP_START_BIT )
                            {
                                 VALVA_AEROFLUXUS_START();
                                // xEventGroupClearBits(event,BREAST_PUMP_START_BIT);
                                // xEventGroupSetBits(event,BREAST_VALVE_AEROFLUXUS_BIT);
                            }
                        }
                        else
                        {
                            output_msg->packet.systeam_tick = 0;
                            xEventGroupClearBits(event,BREAST_TIM_SET_BIT | BREAST_PUMP_START_BIT);
                            xEventGroupSetBits(event,BREAST_PUMP_PAUSE_BIT);
                        }
                         xQueueSend(output_msg_queue,output_msg,0); 
                        last_min_set = output_msg->packet.task_min_set;
                        break;
                    }
                }
            }
        }
        else if((bits & BREAST_SLEEP_BIT ) == BREAST_SLEEP_BIT)
        {      
            app_sys_sleep();
            bits = xEventGroupGetBits(event);   
            if((bits & BREAST_PUMP_PAUSE_BIT ) == BREAST_PUMP_PAUSE_BIT)
            {
              msg_strcut_init(&output_msg->packet);
              led_display_pause_state(&output_msg->packet);
              while(gpio_input_bit_get(GPIOB, GPIO_PIN_3) == 0);
            }
            
        }
        // 
        if( Set_time_fail == pdTRUE)
        {
            Set_time_fail = pdFALSE;
            output_msg->packet.task_min_set = last_min_set;
        }
        vTaskDelay(10);
    }
}


int app_get_ctrl_packet(void *data)
{
    int error = pdFALSE;
    
    error = xQueueReceive(output_msg_queue,data,0);
    return error;
}

EventGroupHandle_t get_evemt_handle(void)
{
    return event;
}

void app_task_init(void)
{
    //
    bsp_InitKey(); 

    output_msg = malloc(sizeof(breast_output_msg_t));   
    if(output_msg == NULL)
    {
        asm("nop");
    }

    memset(output_msg,0,sizeof(breast_output_msg_t));
    app_gear_default_set(output_msg);
    //
    output_msg_queue = xQueueCreate(5,sizeof(breast_output_msg_t));   
    if(output_msg_queue == NULL)
    {
        asm("nop");
        //SEGGER_RTT_printf(0,"Create output_msg_queue error...\r\n");
    }
    //
    event = xEventGroupCreate();
    if(event == NULL)
    {
        asm("nop");
        //SEGGER_RTT_printf(0,"Create event error...\r\n");
    }
    
    //
    if(xTaskCreate(key_task,"key_task",64,(void*)output_msg,configMAX_PRIORITIES-3,&key_task_Handle) == pdPASS)
    {
        asm("nop");
        //SEGGER_RTT_printf(0,"Create key_task sucess...\r\n");
    }
    //
    if(xTaskCreate(led_display_task,"led_display_task",64,(void*)&output_msg->packet,configMAX_PRIORITIES-5,&led_display_task_Handle) == pdPASS)
    {
        asm("nop");
        //SEGGER_RTT_printf(0,"Create led_display_task sucess...\r\n");
    }
}


void app_task_deinit(void)
{
    vTaskDelete( key_task_Handle );
    vTaskDelete( led_display_task_Handle );
    vQueueDelete(output_msg_queue);
    //vQueueDelete(key_led_queue);
    //vQueueDelete(fun_msg_queue);
    //vQueueDelete(xQueueSet);
    free(output_msg);
}
